#include "mytask.h"
#include "QHostAddress"
#include <formsrv.h>
#include <time.h>
#include <QDateTime>
#include <QQueue>
#include "dealexcelfile.h"
#include <QDir>
MyTask::MyTask()
{
    SocketDescriptor = 0;
    m_socket = NULL;
    tmpSocke = NULL;
    m_client = NULL;
    //m_timer = NULL;
    m_qmsgQue.clear();
    m_bIsStop = false;
    m_nRowNum = 0;
    LastAliveTime = 0;
    m_IP = "";
    m_Log.SetFilePath(QDir::currentPath()+"/log");
    //m_timer = new QTimer;
    //connect(m_timer,SIGNAL(timeout()),this,SLOT(CheckAlive()));
    //m_timer->start(5000);
}

MyTask::~MyTask()
{

    //qDebug()<<"!!!!!!!!!"<<m_socket->isValid()<<m_socket->state()<<m_socket->objectName()<<m_socket;
    if(m_socket)
    {
        delete m_socket;
        //m_socket = NULL;
    }
    //    if(m_timer)
    //    {
    //        delete m_timer;
    //    }
    //qDebug()<<"close----------------------------"<<m_socket;
    m_qmsgQue.clear();
}
void MyTask::Stop()
{
    m_bIsStop = true;
}

void MyTask::Start()
{
    m_bIsStop = false;
}
void MyTask::CreateSocket()
{
    if(!SocketDescriptor) return;
    m_socket = new QTcpSocket;
    m_socket->setSocketDescriptor(SocketDescriptor);
    QString sockIp = m_socket->peerAddress().toString();
    //列表中已存在ip,不需要添加,直进行更新
    if(getForm()->CheckexistIp(sockIp,m_nRowNum,SocketDescriptor))
    {
        m_Log.InitLog(sockIp);
        m_Log.LogMsg(tr("客户端：%1重连监控").arg(sockIp));
        //qDebug()<<"exist ip"<<sockIp;
        //防止已经连接的再次连接(客户端已做禁止重连处理)
        if(getForm()->getClientNetState(m_nRowNum) == "已连接")
        {
            m_bIsStop = true;
            //            int lastSockID = getForm()->getClientID(m_nRowNum);
            //            //qDebug()<<"delete old connect:"<<lastSockID<<"current connect:"<<SocketDescriptor;
            //            m_Log.LogMsg(tr("已连接客户端试图再次连接:删除%1,新建%2,state:%3").arg(lastSockID).arg(SocketDescriptor).arg(m_socket->state()));
            //            tmpSocke = new QTcpSocket;
            //            tmpSocke->setSocketDescriptor(lastSockID);
            //            tmpSocke->close();
            //msleep(100);
            //delete tmpSocke;
        }
        else
        {
            //getForm()->slot_UpdateClientID(m_nRowNum,SocketDescriptor);
            emit sig_UpdateClientID(m_nRowNum,SocketDescriptor);
            //getForm()->slot_UpdateClientNetState(m_nRowNum,"已连接");
            emit sig_UpdateClientNetState(m_nRowNum,"已连接");
        }
        //        //getForm()->slot_UpdateClientID(m_nRowNum,SocketDescriptor);
        //        emit sig_UpdateClientID(m_nRowNum,SocketDescriptor);
        //        //getForm()->slot_UpdateClientNetState(m_nRowNum,"已连接");
        //        emit sig_UpdateClientNetState(m_nRowNum,"已连接");
    }
    //列表中不存在ip,进行添加,并添加到form的ip记录中
    else
    {
        //在判断到map中没有时立即添加了
        //getForm()->slot_InsertClient(SocketDescriptor,sockIp,"","车道连接成功",m_nRowNum);
        m_Log.InitLog(sockIp);
        m_Log.LogMsg(tr("客户端：%1与监控建立连接").arg(sockIp));
        //        //getForm()->slot_InsertClient(SocketDescriptor,sockIp,"","车道连接成功",m_nRowNum);
        //        //getServer()->slot_InsetNewIpAndRow(sockIp,m_nRowNum);
        //        //m_Log.LogMsg(tr("客户端：%1添加到监控列表").arg(sockIp));
        //        //emit sig_InsertClient(SocketDescriptor,sockIp,"","车道连接成功",m_nRowNum);
    }
    //qDebug()<<"create end"<<m_socket->peerAddress().toString()<<m_socket->state()<<m_socket->socketDescriptor();
}
void MyTask::CheckNetState()
{
    //检测到连接断开或者停止监控事件,销毁当前线程及连接套接字
    //qDebug()<<"run m_bIsStop:"<<m_bIsStop<<"state:"<<(int) m_socket->state();
    if(m_socket->state() != QTcpSocket::ConnectedState || m_bIsStop)
    {
        m_Log.LogMsg(tr("disconnect:%1,%2").arg(m_socket->state()).arg(m_bIsStop));
        //qDebug()<<"stop-------------------------------------"<<m_socket->state()<<m_bIsStop<<SocketDescriptor<<m_socket->socketDescriptor();
        m_socket->disconnectFromHost();
        m_socket->abort();
        m_socket->close();
        //qDebug()<<"disconnect end"<<m_socket->state()<<m_socket->isValid();
        //getForm()->slot_UpdateClientNetState(m_nRowNum,"未连接");
        emit sig_UpdateClientNetState(m_nRowNum,"未连接");
        m_bIsStop = true;
    }
    else
    {
        //getForm()->slot_UpdateClientNetState(m_nRowNum,"已连接");
        //emit sig_UpdateClientNetState(m_nRowNum,"已连接");
    }
    //qDebug()<<"check end"<<m_socket->peerAddress().toString()<<m_socket->state();

}
void MyTask::run()
{
    //检测到有客户端发消息视图连接时不要立即创建连接,(有些客户端消息连一下接着断开)
    msleep(500);
    CreateSocket();
    while(true)
    {
        CheckAlive();
        CheckNetState();
        if(m_bIsStop) break;
        AnalyzeData();
        msleep(100);
    }
}
void MyTask::CheckAlive()
{
    QMutexLocker lock(&mutex);
    time_t currenttime = 0;
    time(&currenttime);
    // qDebug()<<"alive time:"<<LastAliveTime;
    if(m_bIsStop)
    {
        return;
    }
    if(currenttime - LastAliveTime > 20 && LastAliveTime != 0)
    {
        //m_timer->stop();
        m_bIsStop = true;
    }
    else
    {
        m_bIsStop = false;
    }
}
quint64 MyTask::ReadDateFromSocket(char* data,int len,int timeOut)
{
    quint64 readLen = 0;
    while(readLen < len)
    {
        data = data + readLen;
        if(m_socket->bytesAvailable() == 0)
        {
            if(!m_socket->waitForReadyRead(timeOut))
            {
                break;
            }
        }
        readLen += m_socket->read(data,len-readLen);
    }
    return readLen;
}

void MyTask::AnalyzeData()
{
    PacketHead head;
    initInfo init;
    vehTypeInfo vehicle;
    vehQueueInfo vehQueue;
    myVehInfo currentVeh;
    vcrLogInfo logInfo;
    memset(&head,0,sizeof(head));
    memset(&init,0,sizeof(init));
    memset(&vehQueue,0,sizeof(vehQueue));
    memset(&currentVeh,0,sizeof(currentVeh));
    memset(&logInfo,0,sizeof(vcrLogInfo));
    do
    {
        quint64 readLen = ReadDateFromSocket((char*)&head,sizeof(head),200);
        if(readLen <= 0)
        {
            return;
        }
        if(head.type != 0)
        {
            //qDebug()<<"head type:"<<head.type<<head.length<<readLen;
        }
        quint32 msgLen = head.length;
        switch(head.type)
        {
        case 0:
            time(&LastAliveTime);
            break;
        case 1:
            //初始化信息
            time(&LastAliveTime);
            readLen = ReadDateFromSocket((char*)&init,sizeof(init),300);
            HandleInitInfo(head.laneId,init);
            break;
        case 2:
            //当前取卡车辆信息
            time(&LastAliveTime);
            readLen = ReadDateFromSocket((char*)&currentVeh,sizeof(currentVeh),300);
            HandleCurVehInfo(currentVeh);
            break;
        case 3:
            //同步日志信息
            time(&LastAliveTime);
            readLen = ReadDateFromSocket((char*)&logInfo,sizeof(logInfo),300);
            HandleLogMsg(msgLen,logInfo);
            break;
        case 4:
            //关闭报文
            time(&LastAliveTime);
            emit sig_RecMsg(m_nRowNum,QString("车型识别程序关闭")+"\n"+"["+QDateTime::currentDateTime().toString("hh:mm:ss")+"]");
            m_Log.LogMsg(QString("报文信息：关闭报文"));
            break;
        case 21:
            //车辆入队
            time(&LastAliveTime);
            readLen = ReadDateFromSocket((char*)&vehQueue,sizeof(vehQueue),300);
            emit sig_RecMsg(m_nRowNum,QString("车辆入队")+"\n"+"["+QDateTime::currentDateTime().toString("hh:mm:ss")+"]");
            m_Log.LogMsg(QString("报文信息：车辆入队 车队信息为："));
            HandleVehQueueInfo(vehQueue);
            break;
        case 22:
            //车辆出队
            time(&LastAliveTime);
            readLen = ReadDateFromSocket((char*)&vehQueue,sizeof(vehQueue),300);
            emit sig_RecMsg(m_nRowNum,QString("车辆出队") + "\n"+"[" + QDateTime::currentDateTime().toString("hh:mm:ss") + "]");
            m_Log.LogMsg(QString("报文信息：车辆出队 车队信息为："));
            HandleVehQueueInfo(vehQueue);
            break;
        case 23:
            //删除超时车
            time(&LastAliveTime);
            emit sig_RecMsg(m_nRowNum,QString("删除超时车辆")+"\n"+"["+QDateTime::currentDateTime().toString("hh:mm:ss")+"]");
            m_Log.LogMsg(QString("报文信息：删除超时车"));
            break;
        case 24:
            //车牌纠正
            time(&LastAliveTime);
            emit sig_RecMsg(m_nRowNum,QString("车牌纠错")+"\n"+"["+QDateTime::currentDateTime().toString("hh:mm:ss")+"]");
            m_Log.LogMsg(QString("报文信息：车牌纠错"));
            break;
        case 25:
            //队列清空
            time(&LastAliveTime);
            emit sig_RecMsg(m_nRowNum,QString("清空车型队列")+"\n"+"["+QDateTime::currentDateTime().toString("hh:mm:ss")+"]");
            vehQueue.vehCount = 0;
            m_Log.LogMsg(QString("报文信息：队列清空 队列信息："));
            HandleVehQueueInfo(vehQueue);
            break;
        case 26:
            //倒车
            readLen = ReadDateFromSocket((char*)&vehQueue,sizeof(vehQueue),300);
            emit sig_RecMsg(m_nRowNum,QString("车辆倒车")+"\n"+"["+QDateTime::currentDateTime().toString("hh:mm:ss")+"]");
            m_Log.LogMsg(QString("报文信息：倒车"));
            HandleVehQueueInfo(vehQueue);
            break;
        default:
            time(&LastAliveTime);
            emit sig_RecMsg(m_nRowNum,QString("未知事件")+"\n"+"["+QDateTime::currentDateTime().toString("hh:mm:ss")+"]");
            m_Log.LogMsg(QString("报文信息：未知事件"));
            break;
        }
    }
    while(m_socket->bytesAvailable());
}

void MyTask::HandleInitInfo(int laneID,initInfo &init)
{
    QString device = "断开";
    QString useVpr = "未启用";
    QString useTimeOut = "未启用";
    QString useMoreDel = "未启用";
    //qDebug()<<"init info"<<init.deviceState<<init.useVpr<<init.useTimeOut<<init.useMoreDel;
    if(init.deviceState == 1)
    {
        device = "连接";
        //getDealExecl()->SetPointStatue(m_socket->peerAddress().toString(),1);
    }
    //    else
    //    {
    //        getDealExecl()->SetPointStatue(m_socket->peerAddress().toString(),0);
    //    }
    if(init.useVpr == 1)
    {
        useVpr = "启用";
    }
    if(init.useTimeOut == 1)
    {
        useTimeOut = "启用";
    }
    if(init.useMoreDel == 1)
    {
        useMoreDel = "启用";
    }
    emit sig_RecMsg(m_nRowNum,QString("车型识别初始化")+"\n"+"["+QDateTime::currentDateTime().toString("hh:mm:ss")+"]");
    emit sig_UpdateClientInitState(m_nRowNum,QString::number(laneID),device,useVpr,useTimeOut,useMoreDel);
    //getForm()->slot_UpdateClientInitState(m_nRowNum,QString::number(laneID),device,useVpr,useTimeOut,useMoreDel);
    //写初始化报文日志
    m_Log.LogMsg(QString("报文信息：初始化报文 ")
                 +tr("设备状态:%1").arg(device)+" "
                 +tr("启用车牌纠错:%2").arg(useVpr)+" "
                 +tr("启用超时检测:%3").arg(useTimeOut)+" "
                 +tr("启用多车检测:%4").arg(useMoreDel));
}

void MyTask::HandleVehQueueInfo(vehQueueInfo &vehQue)
{
    myQueue tmpvehQueue;
    tmpvehQueue.clear();
    int tmpVehCount = vehQue.vehCount;
    if(tmpVehCount > 5) tmpVehCount = 5;
    for(int i = 0;i < tmpVehCount;i++)
    {
        tmpvehQueue.enqueue(vehQue.vheQueue[i]);
    }
    emit sig_UpdateVehQueue(SocketDescriptor,tmpvehQueue,vehQue.vehCount);

    int judge=0;
    //    if(vehQue.vehCount>=0&&vehQue.vehCount<=5)
    //    {
    //        judge=vehQue.vehCount;
    //        judge = qMin(5,vehQue.vehCount);
    //    }
    //    else if(vehQue.vehCount>5)
    //    {
    //        judge=5;
    //    }
    if(vehQue.vehCount >=0)
    {
        judge = qMin(5,(int)vehQue.vehCount);
    }
    //向日志写入队列信息
    int queueNum=0;
    QString msgForLog;
    msgForLog.clear();
    msgForLog.append(tr("队列车辆数：%1； ").arg(vehQue.vehCount));
    if(judge==0)
    {
        msgForLog.append(tr("队列车辆数=%1 ").arg(vehQue.vehCount)+QString("队列为空！"));
    }
    for(queueNum=0;queueNum<judge;queueNum++)
    {
        msgForLog.append(QString("第")+tr("%1").arg(queueNum+1)+QString("辆车车型：")+tr("[%1]").arg(vehQue.vheQueue[queueNum].vehType)
                         +" "+tr("来车时间：[%1]").arg(QDateTime::fromTime_t(vehQue.vheQueue[queueNum].vehTime).toString("hh:mm:ss"))+"； ");
    }
    m_Log.LogMsg(msgForLog);
}

void MyTask::HandleCurVehInfo(myVehInfo &curVeh)
{
    emit sig_RecMsg(m_nRowNum,QString("车辆取卡")+"\n"+"["+QDateTime::currentDateTime().toString("hh:mm:ss")+"]");
    emit sig_UpdateCurVeh(SocketDescriptor,curVeh);
    //向日志文件中写入当前车辆信息
    m_Log.LogMsg(QString("报文信息：按键取卡，当前车辆信息 ")+tr("返回车型为:[%1]")
                 .arg(curVeh.finalVehType)+" "+tr("车牌为:[%2]").arg(curVeh.vehPlate)+" "+tr("按键时间:[%3]").arg(QDateTime::fromTime_t(curVeh.curTime).toString("hh:mm:ss")));
}

void MyTask::HandleLogMsg(quint32 msgLen,vcrLogInfo &logInfo)
{
    QString logTime = QDateTime::fromTime_t(logInfo.logTime).toString("hh-mm-ss-z");
    QString logmsg = QString::fromLocal8Bit(logInfo.logMsg,qMin((int)qstrlen(logInfo.logMsg),(int)sizeof(logInfo.logMsg)));
    emit sig_LogMsg(SocketDescriptor,"["+logTime+"]"+QString("日志信息:")+logmsg);
    //将text_Display显示内容写入日志
    m_Log.LogMsg(QString("日志信息：")+logmsg);
}


void MyTask::SendMsg(int sockDes,QString msg)
{
    QMutexLocker lock(&mutex);
    if(sockDes == SocketDescriptor)
    {
        m_qmsgQue.enqueue(msg);
    }
}
